home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2000 / MacHack 2000.toast / pc / The Hacks / MacHacksBug / Python 1.5.2c1 / Extensions / Imaging / PIL / ImImagePlugin.py < prev    next >
Encoding:
Text File  |  2000-06-23  |  7.7 KB  |  317 lines

  1. #
  2. # The Python Imaging Library.
  3. # $Id: ImImagePlugin.py,v 1.1.1.2 1999/01/13 09:40:04 sjoerd Exp $
  4. #
  5. # IFUNC IM file handling for PIL
  6. #
  7. # history:
  8. # 95-09-01 fl    Created.  
  9. # 97-01-03 fl    Save palette images
  10. # 97-01-08 fl    Added sequence support
  11. # 97-01-23 fl    Added P and RGB save support
  12. # 97-05-31 fl    Read floating point images
  13. # 97-06-22 fl    Save floating point images
  14. # 97-08-27 fl    Read and save 1-bit images
  15. # 98-06-25 fl    Added support for RGB+LUT images
  16. # 98-07-02 fl    Added support for YCC images
  17. # 98-07-15 fl    Renamed offset attribute to avoid name clash
  18. # 98-12-29 fl    Added I;16 support
  19. #
  20. # Copyright (c) Secret Labs AB 1997-98.
  21. # Copyright (c) Fredrik Lundh 1995-97.
  22. #
  23. # See the README file for information on usage and redistribution.
  24. #
  25.  
  26.  
  27. __version__ = "0.6"
  28.  
  29. import regex, string
  30. import Image, ImageFile, ImagePalette
  31.  
  32.  
  33. # --------------------------------------------------------------------
  34. # Standard tags
  35.  
  36. COMMENT = "Comment"
  37. DATE = "Date"
  38. EQUIPMENT = "Digitalization equipment"
  39. FRAMES = "File size (no of images)"
  40. LUT = "Lut"
  41. NAME = "Name"
  42. SCALE = "Scale (x,y)"
  43. SIZE = "Image size (x*y)"
  44. MODE = "Image type"
  45.  
  46. TAGS = { COMMENT:0, DATE:0, EQUIPMENT:0, FRAMES:0, LUT:0, NAME:0,
  47.      SCALE:0, SIZE:0, MODE:0 }
  48.  
  49. OPEN = {
  50.     # ifunc93/p3cfunc formats
  51.     "0 1 image": ("1", "1"),
  52.     "L 1 image": ("1", "1"),
  53.     "Greyscale image": ("L", "L"),
  54.     "Grayscale image": ("L", "L"),
  55.     "RGB image": ("RGB", "RGB;L"),
  56.     "RLB image": ("RGB", "RLB"),
  57.     "RYB image": ("RGB", "RLB"),
  58.     "B1 image": ("1", "1"),
  59.     "B2 image": ("P", "P;2"),
  60.     "B4 image": ("P", "P;4"),
  61.     "X 24 image": ("RGB", "RGB"),
  62.     # old p3cfunc formats
  63.     "RGB3 image": ("RGB", "RGB;T"),
  64.     "RYB3 image": ("RGB", "RYB;T"),
  65.     # extensions
  66.     "RGBA image": ("RGBA", "RGBA;L"),
  67.     "RGBX image": ("RGBX", "RGBX;L"),
  68.     "CMYK image": ("CMYK", "CMYK;L"),
  69.     "YCC image": ("YCbCr", "YCbCr;L"),
  70. }
  71.  
  72. # ifunc95 extensions
  73. for i in ["8", "8S", "16", "16S", "32", "32F"]:
  74.     OPEN["L %s image" % i] = ("F", "F;%s" % i)
  75.     OPEN["L*%s image" % i] = ("F", "F;%s" % i)
  76. for i in ["16", "16B"]:
  77.     OPEN["L %s image" % i] = ("I;%s" % i, "I;%s" % i)
  78.     OPEN["L*%s image" % i] = ("I;%s" % i, "I;%s" % i)
  79. for i in ["32S"]:
  80.     OPEN["L %s image" % i] = ("I", "I;%s" % i)
  81.     OPEN["L*%s image" % i] = ("I", "I;%s" % i)
  82. for i in range(2, 33):
  83.     OPEN["L*%s image" % i] = ("F", "F;%s" % i)
  84.  
  85.  
  86. # --------------------------------------------------------------------
  87. # Read IM directory
  88.  
  89. split = regex.compile("^\([A-Za-z][^:]*\):[ \t]*\(.*\)[ \t]*$")
  90.  
  91. class ImImageFile(ImageFile.ImageFile):
  92.  
  93.     format = "IM"
  94.     format_description = "IFUNC Image Memory"
  95.  
  96.     def _open(self):
  97.  
  98.     # Quick rejection: if there's not an LF among the first
  99.     # 100 bytes, this is (probably) not a text header.
  100.  
  101.     if not "\n" in self.fp.read(100):
  102.         raise SyntaxError, "not an IM file"
  103.     self.fp.seek(0)
  104.  
  105.     n = 0
  106.  
  107.     # Default values
  108.     self.info[MODE] = "L"
  109.     self.info[SIZE] = (512, 512)
  110.     self.info[FRAMES] = 1
  111.  
  112.         self.rawmode = "L"
  113.  
  114.     while 1:
  115.  
  116.         s = self.fp.read(1)
  117.  
  118.         # Some versions of IFUNC uses \n\r instead of \r\n...
  119.         if s == "\r":
  120.         continue
  121.  
  122.         if not s or s[0] == chr(0) or s[0] == chr(26):
  123.         break
  124.  
  125.         # FIXME: this may read whole file if not a text file
  126.         s = s + self.fp.readline()
  127.  
  128.         if len(s) > 100:
  129.         raise SyntaxError, "not an IM file"
  130.  
  131.         if s[-2:] == '\r\n':
  132.         s = s[:-2]
  133.         elif s[-1:] == '\n':
  134.         s = s[:-1]
  135.  
  136.         try:
  137.         hit = split.match(s)
  138.         except regex.error, v:
  139.         raise SyntaxError, "not an IM file"
  140.  
  141.         if hit >= 0:
  142.  
  143.         k, v = split.group(1,2)
  144.  
  145.         # Convert value as appropriate
  146.         if k in [FRAMES, SCALE, SIZE]:
  147.             i = string.find(v, "*")
  148.             if i >= 0:
  149.             v = v[:i] + "," + v[i+1:]
  150.             v = eval(v)
  151.         elif k == MODE and OPEN.has_key(v):
  152.             v, self.rawmode = OPEN[v]
  153.  
  154.         # Add to dictionary. Note that COMMENT tags are
  155.         # combined into a list of strings.
  156.         if k == COMMENT:
  157.             if self.info.has_key(k):
  158.             self.info[k].append(v)
  159.             else:
  160.             self.info[k] = [v]
  161.         else:
  162.             self.info[k] = v
  163.  
  164.         if TAGS.has_key(k):
  165.             n = n + 1
  166.  
  167.         else:
  168.  
  169.         raise SyntaxError, "Syntax error in IM header: " + s
  170.  
  171.     if not n:
  172.         raise SyntaxError, "Not an IM file"
  173.  
  174.     # Basic attributes
  175.     self.size = self.info[SIZE]
  176.     self.mode = self.info[MODE]
  177.  
  178.     # Skip forward to start of image data
  179.     while s and s[0] != chr(26):
  180.         s = self.fp.read(1)
  181.     if not s:
  182.         return
  183.  
  184.     if self.info.has_key(LUT):
  185.         # convert lookup table to palette or lut attribute
  186.         raw_palette = self.fp.read(768)
  187.         p = map(ord, raw_palette)
  188.         f_greyscale = 1 # greyscale palette
  189.         f_linear = 1 # linear greyscale palette
  190.         for i in range(256):
  191.         if p[i] != p[i+256] or p[i] != p[i+512]:
  192.             f_greyscale = 0
  193.         elif p[i] != i:
  194.             f_linear = 0
  195.         if self.mode == "L":
  196.         if f_greyscale:
  197.             if not f_linear:
  198.             self.lut = p[:256]
  199.         else:
  200.             self.mode = "P"
  201.             self.palette = ImagePalette.raw("RGB;L", raw_palette)
  202.         elif self.mode == "RGB":
  203.         if not f_greyscale or not f_linear:
  204.             self.lut = p
  205.  
  206.     self.frame = 0
  207.  
  208.     self.__offset = offs = self.fp.tell()
  209.  
  210.     self.__fp = self.fp # FIXME: hack
  211.  
  212.         if self.rawmode[:2] == "F;":
  213.  
  214.             # ifunc95 formats
  215.             try:
  216.                 # use bit decoder (if necessary)
  217.                 bits = string.atoi(self.rawmode[2:])
  218.                 if bits not in [8, 16, 32]:
  219.                     self.tile = [("bit", (0,0)+self.size, offs,
  220.                                  (bits, 8, 3, 0, -1))]
  221.                     return
  222.             except ValueError:
  223.                 pass
  224.  
  225.     if self.rawmode in ["RGB;T", "RYB;T"]:
  226.         # Old LabEye/3PC files.  Would be very surprised if anyone
  227.         # ever stumbled upon such a file ;-)
  228.         size = self.size[0] * self.size[1]
  229.         self.tile = [("raw", (0,0)+self.size, offs, ("G", 0, -1)),
  230.              ("raw", (0,0)+self.size, offs+size, ("R", 0, -1)),
  231.              ("raw", (0,0)+self.size, offs+2*size, ("B", 0, -1))]
  232.     else:
  233.         # LabEye/IFUNC files
  234.         self.tile = [("raw", (0,0)+self.size, offs, (self.rawmode, 0, -1))]
  235.  
  236.     def seek(self, frame):
  237.     
  238.     if frame < 0 or frame >= self.info[FRAMES]:
  239.         raise EOFError, "seek outside sequence"
  240.  
  241.     if self.frame == frame:
  242.         return
  243.  
  244.     self.frame = frame
  245.  
  246.     if self.mode == "1":
  247.         bits = 1
  248.     else:
  249.         bits = 8 * len(self.mode)
  250.  
  251.     size = ((self.size[0] * bits + 7) / 8) * self.size[1]
  252.     offs = self.__offset + frame * size
  253.  
  254.     self.fp = self.__fp
  255.  
  256.     self.tile = [("raw", (0,0)+self.size, offs, (self.rawmode, 0, -1))]
  257.  
  258.     def tell(self):
  259.     
  260.     return self.frame
  261.  
  262. #
  263. # --------------------------------------------------------------------
  264. # Save IM files
  265.  
  266. SAVE = {
  267.     # mode: (im type, raw mode)
  268.     "1": ("0 1", "1"),
  269.     "L": ("Greyscale", "L"),
  270.     "P": ("Greyscale", "P"),
  271.     "I": ("L 32S", "I;32S"),
  272.     "I;16": ("L 16", "I;16"),
  273.     "I;16B": ("L 16B", "I;16B"),
  274.     "F": ("L 32F", "F;32F"),
  275.     "RGB": ("RGB", "RGB;L"),
  276.     "RGBA": ("RGBA", "RGBA;L"),
  277.     "RGBX": ("RGBX", "RGBX;L"),
  278.     "CMYK": ("CMYK", "CMYK;L"),
  279.     "YCbCr": ("YCC", "YCbCr;L")
  280. }
  281.  
  282. def _save(im, fp, filename, check=0):
  283.  
  284.     try:
  285.     type, rawmode = SAVE[im.mode]
  286.     except KeyError:
  287.     raise ValueError, "Cannot save %s images as IM" % im.mode
  288.  
  289.     try:
  290.     frames = im.encoderinfo["frames"]
  291.     except KeyError:
  292.     frames = 1
  293.  
  294.     if check:
  295.     return check
  296.  
  297.     fp.write("Image type: %s image\r\n" % type)
  298.     if filename:
  299.     fp.write("Name: %s\r\n" % filename)
  300.     fp.write("Image size (x*y): %d*%d\r\n" % im.size)
  301.     fp.write("File size (no of images): %d\r\n" % frames)
  302.     if im.mode == "P":
  303.     fp.write("Lut: 1\r\n")
  304.     fp.write("\000" * (511-fp.tell()) + "\032")
  305.     if im.mode == "P":
  306.     fp.write(im.im.getpalette("RGB", "RGB;L")) # 768 bytes
  307.     ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, 0, -1))])
  308.  
  309. #
  310. # --------------------------------------------------------------------
  311. # Registry
  312.  
  313. Image.register_open("IM", ImImageFile)
  314. Image.register_save("IM", _save)
  315.  
  316. Image.register_extension("IM", ".im")
  317.